package intermouse;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

/**
 * @author      Szórádi Balázs
 * @version     1.0
 * @since       2013-03-24
 */
public class Field {
	
	
	/**
	 * A mezőn lévő FieldObject-ek tárolója
	 */
	List<FieldObject> obj;
	
	/**
	 * A mezőn lévő szagok tárolója
	 */
	private List<Smell> smells;

	/**
	 * Referenciák a mezővel szomszédos mezőkre
	 */
	private List<Field> adjacentFields;
	
	private int coordsx, coordsy;
	
	/**
	 * Konstruktor
	 */
	public Field(){
		obj = new ArrayList<FieldObject>();
		adjacentFields= new ArrayList<Field>();
		smells  = new ArrayList<Smell>();
	}
	
	public void setCoords(int x, int y)
	{
		coordsx = x;
		coordsy = y;
	}
	
	/**
	 * Szomszédos mezők listájának lekérdezése.
	 * @return Szomszédos mezők listája.
	 */
	public List<Field> getAdjacentFields(){
		System.out.println(">> Field.getAdjacentFields() : List<Field>");
		System.out.println("<< return");
//		List<Field> ret = new ArrayList(); //inkább shallow copy, a level konstruktora is ezt a fvt használja a referenciák kitöltésére
//		for(int i = 0; i < adjacentFields.size(); i++)
//			ret.add(adjacentFields.get(i));
//		return ret;
		return adjacentFields;
	}
	
	/**
	 * Mezőn lévő szagok listájának lekérdezése.
	 * @return Mezőn lévő szagok listája.
	 */
	public List<Smell> getSmells(){
		System.out.println(">> Field.getSmells() : List<Smell>");
		System.out.println("<< return");
		return smells;
	}
	
	/**
	 * Eltünteti a mezőn lévő hangyaszagot, úgy, hogy meghívja a smells
	 * lista minden elemére a deodorantReaction() függvényt, ha hamissal
	 * tér vissza, akkor nem töröljük, ha igazzal akkor igen, mert az hangyaszag.
	 * 
	 * @param radius A radius paraméterrel megadjuk, hogy milyen távolságban hívjuk meg a
	 * környező mezőkre is ezt a függvényt.
	 * @return boolean: sikerült-e hangyaszagot törölni
	 */
	public boolean applyAntDeodorant(int radius){
		System.out.println(">> Field.applyAntDeodorant() : void");
		boolean ret = false;
		for(Smell s : smells){
			if(s.deodorantReaction()) ret = true;
		}
		System.out.println("<< return");
		return ret;
	}
	
	/**
	 * Ha valami támadást akar indítani ez ellen a mező ellen (illetve a
	 * rajta lévő objektumok ellen), akkor ezt a függvényt hívja meg, ami
	 * továbbhív: a rajta lévő objektumok attack() függvényét hívja meg.
	 * 
	 * @return Visszatérési értéke boolean. Akkor igaz, ha egy hangya meghalt
	 * a támadás során (valamelyik FieldObject igazzal tért vissza).
	 */
	public boolean attack(){
		System.out.println(">> Field.attack() : boolean");
		boolean ret = false;
		for(FieldObject i : obj){
			if(i.attack()) ret = true;
		}
		System.out.println("<< return");
		return ret;
	}
	
	/**
	 * Meghívja a rajta lévő objektumok beginRound() metódusát.
	 * 
	 * @return Void visszatérési érték.
	 */
	public void beginRound(){
		System.out.println(">> Field.beginRound() : void");
		for(FieldObject o : obj){
			if(o.getDead()) obj.remove(o);
		}
		for(Smell i : smells){
			i.beginRound();
		}
		System.out.println("<< return");
	}
	
	/**
	 * Megadja, hogy a referenciaként kapott hangya ráléphet-e az adott mezőre,
	 * ehhez meghívja az obj listában tárolt FieldObject objektumok
	 * canStep(Ant ant) függvényeit.
	 * 
	 * @return Boolean érték, amely igaz, ha a hangya az adott mezőre léphet.
	 */
	public boolean canStep(Ant ant){
		boolean ret = true;
		System.out.println(">> Field.canStep(Ant) : boolean");
		for(FieldObject i : obj){
			if(!i.canStep(ant)) ret = false;
		}
		if (ret == true) //beletrollkodás: ki kell törölni a field közül is a referenciát
		{
			obj.remove(ant);
		}
		System.out.println("<< return");
		return ret;
	}
	
	/**
	 * Megadja, hogy a referenciaként kapott hangyászsün ráléphet-e az adott mezőre,
	 * ehhez meghívja az obj listában tárolt FieldObject objektumok
	 * canStep(AntEater antEater, int direction) függvényeit.
	 * 
	 * @return Boolean érték, amely igaz, ha a hangyászsün az adott mezőre léphet.
	 */
	public boolean canStep(AntEater anteater, int direction){
		boolean ret = true;
		System.out.println(">> Field.canStep(AntEater, int) : boolean");
		for(FieldObject i : obj){
			if(!i.canStep(anteater, direction)) ret = false;
		}
		System.out.println("<< return");
	    return ret;
	}
	
	
	/**
	 * Megadja, hogy a referenciaként kapott kő ráléphet-e az adott mezőre,
	 * ehhez meghívja az obj listában tárolt FieldObject objektumok
	 * canStep(Stone stone, boolean isFirst, int direction) függvényeit.
	 * 
	 * @return Boolean érték, amely igaz, ha a kő az adott mezőre léphet.
	 */
	public boolean canStep(Stone stone, boolean isFirst, int direction){
		boolean ret = true;
		System.out.println(">> Field.canStep(Stone, boolean, int) : boolean");
		for(FieldObject i : obj){
			if(!i.canStep(stone, isFirst, direction)) ret = false;
		}
		System.out.println("<< return");
	    return ret;
	}
	
	/**
	 * Visszaadja, hogy a mezőn mennyi étel található, ehhez az obj lista
	 * minden elemére meghívja az isFood() függvényt és megszámolja,
	 * hány true értéket kapott vissza.
	 * 
	 * @return Visszatér egy int értékkel, mely a mezőn lévő ételek számával egyenlő.
	 */
	public int getFoodCount(){
		System.out.println(">> Field.getFoodCount() : int");
		int cnt = 0;
		for(FieldObject i : obj){
			if(i.isFood()) cnt++;
		}
		return cnt;
	}
	
	/**
	 * A mezőn lévő halott ételek eltakarítása.
	 * 
	 * @return Void értékkel tér vissza.
	 */
	public void deleteDeadFood(){
		System.out.println(">> Field.deleteDeadFood() : void");
		
		for(FieldObject i : obj){
			if(i.isFood()){
				if(i.getDead()){
					//ez lehet hogy nem fog működni mert azt töröljük épp amin iterálunk
					obj.remove(i);
				}
			}
		}
		
		System.out.println("<< return");
	}
	
	/**
	 * Felvesz egy új elemet (szagot) a smells listába.
	 * 
	 * @param smell A hozzáadandó új szag.
	 * @return Void visszatérési érték.
	 */	
	public void addSmell(Smell smell){
		System.out.println(">> Field.addSmell(Smell) : void");
		smells.add(smell);
		System.out.println("<< return");
	}
	
	/**
	 * Felvesz egy új elemet (FieldObject) az obj listába.
	 * 
	 * @param o A hozzáadandó új FieldObject.
	 * @return Void visszatérési érték.
	 */
	public void addFieldObject(FieldObject o){
		System.out.println(">> Field.addFieldObject() : void");
		obj.add(o);
		System.out.println("<< return");
	}
	
	public String toString()
	{
		return coordsx + "," + coordsy;
	}
}
